const { ccclass, property } = cc._decorator;
const gfx = cc['gfx'];

import { gameHelper } from "../../cccframework/Utils/GameHelpler";
import verlet_simulateBookAssembler from "./verlet_simulateBookAssembler";
@ccclass
// @executeInEditMode
export default class simulateBookSprite extends cc.Sprite {


    meshRenderer: cc.MeshRenderer = null;
    @property
    gravity: number = -0.2;
    // @property
    _bookAngle: number = 0;
    // @property({ type: cc.Integer })
    get bookAngle() {
        return this._bookAngle;
    }
    set bookAngle(v: number) {
        this._bookAngle = v;
        this.updateVertexes();
    }

    _verticalCount = 40;
    _pointList: Array<cc.Vec2> = [];
    _assembler: (verlet_simulateBookAssembler) = null;

    updateVertexes() {
        //@ts-ignore
        let assembler = this._assembler;
        if (!assembler) {
            return;
        }

        assembler.bookPercent = this.bookAngle / 180;
        // assembler.genVert();
        this.setVertsDirty();
    }

    onEnable() {
        super.onEnable();
    }

    // 初始化顶点
    initVerts() {
        let cw = this.node.width;
        let ch = this.node.height;
        for (let i = 0; i < this._verticalCount; i++) {
            let x = (i / (this._verticalCount - 1)) * cw;
            // 初始化平铺的位置
            this._pointList.push(cc.v2(x, 0));
        }
    }
    // 获取新的顶点
    getVerts() {
        return this._pointList;
    }

    update() {
        this.simulate();
        this.applyConstraint();
        this.draw();
    }
    // 模拟重力、加速度
    simulate() {
        let gravity = cc.v2(0, this.gravity);
        for (let i = 1; i < this._pointList.length; i++) {
            let point = this._pointList[i];
            if (point['oldPos']) {
                let oldPos = point['oldPos'] || point;
                let velocity = point.sub(oldPos).normalize().mul(0.5);
                if (point.y <= 0) {
                    gravity.y = Math.max(0, gravity.y);
                }
                point.addSelf(gravity);
                point.addSelf(velocity);
            }
        }
    }
    // 应用约束
    applyConstraint() {
        // 更新最后一个顶点的位置
        let endPos = this.getEndPos();
        this._pointList[this._verticalCount - 1] = endPos;

        let normalDistance = this.node.width / (this._verticalCount - 1);
        for (let i = 0; i < 100; i++) {
            for (let i = this._verticalCount - 1; i >= 1; i--) {
                let secondPoint = this._pointList[i];
                let firstPoint = this._pointList[i - 1];
                let deltaPos = secondPoint.sub(firstPoint);
                let distance = deltaPos.mag();
                let fixDirection = deltaPos.normalize();
                if (distance > normalDistance) {
                    fixDirection = deltaPos.normalize();
                } else if (distance < normalDistance) {
                    fixDirection = deltaPos.normalize().neg();
                } else {
                    continue;
                }
                let fixLen = Math.abs(distance - normalDistance)
                secondPoint['oldPos'] = secondPoint;
                if (i == 1) {
                    let fixHalfVector = fixDirection.mul(fixLen)
                    secondPoint.subSelf(fixHalfVector)
                } else if (i > 1) {
                    // 将两个质点之间的距离纠正为固定长度
                    let fixHalfVector = fixDirection.mul(fixLen * 0.5)
                    firstPoint.addSelf(fixHalfVector)
                    secondPoint.subSelf(fixHalfVector)
                }
            }
        }
    }
    ctx: cc.Graphics = null;
    getEndPos() {
        let cw = this.node.width;
        let ch = this.node.height;
        let rp = cc.v2(cw, 0);
        let lp = cc.v2(-cw, 0);
        let angle2 = 10;
        // let angle2 = 45;
        let radian2 = angle2 * Math.PI / 180;
        let dist2 = cw * 0.8;
        let ctrl2 = rp.add(cc.v2(Math.sin(radian2) * dist2, Math.cos(radian2) * dist2));
        let angle = 30;
        // let angle = -45;
        let radian = angle * Math.PI / 180;
        let dist = cw * 0.9;
        let ctrl = lp.add(cc.v2(Math.sin(radian) * dist, Math.cos(radian) * dist));
        if (CC_PREVIEW) {
            let ctrlWpos = gameHelper.getWpos(ctrl);
            let ctrl2Wpos = gameHelper.getWpos(ctrl2);
            gameHelper.drawAny(null, ctrlWpos, ctrl2Wpos)
        }
        let pos = this.bezier3(rp, ctrl2, ctrl, lp, this.bookAngle / 180);
        return pos;
    }

    // // 抛物线贝塞尔二阶贝塞尔
    // bezier(p0, p2, height, t) {
    //     let t1 = (1 - t) * (1 - t);
    //     let t2 = 2 * t * (1 - t);
    //     let t3 = t * t;
    //     let p1 = cc.v2(p0.x + (p2.x - p0.x) / 2, height);
    //     return p0.mul(t1).add(p1.mul(t2)).add(p2.mul(t3));
    // }
    // 三阶贝塞尔
    bezier3(p0, p1, p2, p3, t) {
        let t0 = (1 - t) * (1 - t) * (1 - t);
        let t1 = 3 * t * (1 - t) * (1 - t);
        let t2 = 3 * t * t * (1 - t);
        let t3 = t * t * t;
        return p0.mul(t0).add(p1.mul(t1)).add(p2.mul(t2)).add(p3.mul(t3));
    }
    // // 抛物线贝塞尔二阶贝塞尔
    // pageBezier(p0, p2, anchorPoint, t) {
    //     let t1 = (1 - t) * (1 - t);
    //     let t2 = 2 * t * (1 - t);
    //     let t3 = t * t;
    //     let x = anchorPoint.x;
    //     // let y = p0.y + (p2.y - p0.y) / 2
    //     let y = p0.y + (p2.y - p0.y) * t;
    //     if (p2.x < p0.x) {
    //         x = anchorPoint.x + (p2.x - p0.x);
    //     }
    //     let ctrl = cc.v2(x, y);
    //     return p0.mul(t1).add(ctrl.mul(t2)).add(p2.mul(t3));
    // }
    // 更新顶点
    draw() {
        this.setVertsDirty();
    }

    _resetAssembler() {
        // this.setVertsDirty();
        this.initVerts();
        let assembler = this._assembler = new verlet_simulateBookAssembler();
        this.updateVertexes();

        assembler.init(this);

        //@ts-ignore
        this._updateColor();
    }
}
